package com.atguigu.seckill.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.tool.utils.Func;
import com.atguigu.common.tool.utils.StringPool;
import com.atguigu.common.utils.R;
import com.atguigu.seckill.feign.CouponFeignService;
import com.atguigu.seckill.feign.ProductFeignService;
import com.atguigu.seckill.service.SeckillService;
import com.atguigu.seckill.to.SecKillSkuRedisTo;
import com.atguigu.seckill.vo.SeckillSessionsWithSkusVO;
import com.atguigu.seckill.vo.SeckillSkuVO;
import com.atguigu.seckill.vo.SkuInfoVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author : wenchao.long
 * @date : Created in 2021/8/23 16:12 周一
 * @description :
 */
@Slf4j
@Service
@AllArgsConstructor
public class SeckillServiceImpl implements SeckillService {

    private final StringRedisTemplate redisTemplate;

    private final RedissonClient redissonClient;

    private final RabbitTemplate rabbitTemplate;

    private final CouponFeignService couponFeignService;

    private final ProductFeignService productFeignService;

    private final String SESSIONS_CACHE_PREFIX = "seckill:sessions:";

    private final String SKUKILL_CACHE_PREFIX = "seckill:skus";

    /**
     * +商品随机码
     */
    private final String SKU_STOCK_SEMAPHORE = "seckill:stock:";


    @Override
    public void uploadSeckillSkuLatest3Days() {
        // 1. 扫描最近3天需要参与秒杀的活动
        R session = couponFeignService.getLates3DaySession();

        if (session.getCode() == 0) {
            List<SeckillSessionsWithSkusVO> sessionData = session.getData(new TypeReference<List<SeckillSessionsWithSkusVO>>() {
            });
            // 缓存到redis
            // 1. 缓存活动信息
            saveSessionInfos(sessionData);
            // 2. 缓存活动的关联商品信息
            saveSessionSkuInfos(sessionData);
        }
    }

    @Override
    public List<SecKillSkuRedisTo> getCurrentSeckillSkus() {
        return null;
    }

    @Override
    public SecKillSkuRedisTo getSkuSeckillInfo(Long skuId) {
        return null;
    }

    @Override
    public String kill(String killId, String key, Integer num) {
        return null;
    }

    private void saveSessionInfos(List<SeckillSessionsWithSkusVO> sessionData) {
        if (Func.isNotEmpty(sessionData)) {
            sessionData.forEach(session -> {
                long startTime = session.getStartTime().getTime();
                long endTime = session.getEndTime().getTime();
                String key = SESSIONS_CACHE_PREFIX + startTime + StringPool.UNDERSCORE + endTime;

                Boolean hasKey = redisTemplate.hasKey(key);
                if (Boolean.FALSE.equals(hasKey)) {
                    List<String> collect = session.getRelationSkus()
                            .stream()
                            .map(item -> item.getPromotionSessionId() + StringPool.UNDERSCORE + item.getSkuId().toString())
                            .collect(Collectors.toList());
                    // 缓存活动信息
                    redisTemplate.opsForList().leftPushAll(key, collect);
                }
            });
        }
    }

    private void saveSessionSkuInfos(List<SeckillSessionsWithSkusVO> sessions) {
        if (Func.isNotEmpty(sessions)) {
            sessions.forEach(session -> {
                BoundHashOperations<String, Object, Object> ops = redisTemplate.boundHashOps(SKUKILL_CACHE_PREFIX);
                List<SeckillSkuVO> relationSkus = session.getRelationSkus();
                if (Func.isNotEmpty(relationSkus)) {
                    relationSkus.forEach(svo -> {
                        // 4. 随机码
                        String token = Func.randomUUID();
                        if (Boolean.FALSE.equals(ops.hasKey(svo.getPromotionSessionId() + StringPool.UNDERSCORE + svo.getSkuId()))) {
                            SecKillSkuRedisTo redisTo = new SecKillSkuRedisTo();

                            R skuInfo = productFeignService.getSkuInfo(svo.getSkuId());
                            if (skuInfo.getCode() == 0) {
                                SkuInfoVO info = skuInfo.getData("skuInfo", new TypeReference<SkuInfoVO>() {
                                });

                                redisTo.setSkuInfo(info);
                            }

                            // 2. sku的秒杀信息
                            BeanUtils.copyProperties(svo, redisTo);

                            // 3. 设置上当前商品的秒杀时间信息
                            redisTo.setStartTime(session.getStartTime().getTime());
                            redisTo.setEndTime(session.getEndTime().getTime());

                            redisTo.setRandomCode(token);

                            redisTo.setSeckillLimit(10);

                            String jsonString = JSON.toJSONString(redisTo);
                            ops.put(svo.getPromotionSessionId() + StringPool.UNDERSCORE + svo.getSkuId(), jsonString);
                        }


                    });
                }
            });
        }
    }
}
